a tool for shared writing and social publishing
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 87 lines 2.5 kB view raw
1import { z } from "zod"; 2import { makeRoute } from "../lib"; 3import type { Env } from "./route"; 4import { idResolver } from "app/(home-pages)/reader/idResolver"; 5import { supabaseServerClient } from "supabase/serverClient"; 6import { Agent } from "@atproto/api"; 7import { getIdentityData } from "actions/getIdentityData"; 8import { createOauthClient } from "src/atproto-oauth"; 9import { 10 normalizePublicationRow, 11 hasValidPublication, 12} from "src/utils/normalizeRecords"; 13import { deduplicateByUri } from "src/utils/deduplicateRecords"; 14 15export type GetProfileDataReturnType = Awaited< 16 ReturnType<(typeof get_profile_data)["handler"]> 17>; 18 19export const get_profile_data = makeRoute({ 20 route: "get_profile_data", 21 input: z.object({ 22 didOrHandle: z.string(), 23 }), 24 handler: async ({ didOrHandle }, { supabase }: Pick<Env, "supabase">) => { 25 // Resolve handle to DID if necessary 26 let did = didOrHandle; 27 28 if (!didOrHandle.startsWith("did:")) { 29 const resolved = await idResolver.handle.resolve(didOrHandle); 30 if (!resolved) { 31 throw new Error("Could not resolve handle to DID"); 32 } 33 did = resolved; 34 } 35 let agent; 36 let authed_identity = await getIdentityData(); 37 if (authed_identity?.atp_did) { 38 try { 39 const oauthClient = await createOauthClient(); 40 let credentialSession = await oauthClient.restore( 41 authed_identity.atp_did, 42 ); 43 agent = new Agent(credentialSession); 44 } catch (e) { 45 agent = new Agent({ 46 service: "https://public.api.bsky.app", 47 }); 48 } 49 } else { 50 agent = new Agent({ 51 service: "https://public.api.bsky.app", 52 }); 53 } 54 55 let profileReq = agent.app.bsky.actor 56 .getProfile({ actor: did }) 57 .then( 58 (res) => res.data, 59 () => undefined, 60 ); 61 62 let publicationsReq = supabase 63 .from("publications") 64 .select("*") 65 .eq("identity_did", did); 66 67 let [profile, { data: rawPublications }] = await Promise.all([ 68 profileReq, 69 publicationsReq, 70 ]); 71 72 // Deduplicate records that may exist under both pub.leaflet and site.standard namespaces 73 const publications = deduplicateByUri(rawPublications || []); 74 75 // Normalize publication records before returning 76 const normalizedPublications = publications 77 .map(normalizePublicationRow) 78 .filter(hasValidPublication); 79 80 return { 81 result: { 82 profile, 83 publications: normalizedPublications, 84 }, 85 }; 86 }, 87});